home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / launchpadbugs / lphelper.py < prev    next >
Text File  |  2008-08-27  |  8KB  |  260 lines

  1. #!/usr/bin/python
  2. # -*- coding: UTF-8 -*-
  3.  
  4.  
  5. import re
  6. from lpconstants import BUG, BLUEPRINT
  7.  
  8.  
  9.  
  10. re_escape = re.compile(ur"\ufffd|\x0f|\x10|\x02|\x07")
  11. def unicode_for_libxml2(text):
  12.     """ helper function to fix encoding errors in libxml2 """
  13.     u = unicode(text, "UTF-8")
  14.     ret = re_escape.sub("??", u)
  15.     return ret.encode("UTF-8")  
  16.  
  17.  
  18. def _attr_ext(i, s):
  19.     if i.startswith("__"):
  20.         return "_%s%s" %(s.__class__.__name__,i)
  21.     else:
  22.         return i
  23.  
  24. def _gen_getter(attr):
  25.     """ Returns a function to return the value of an attribute
  26.     
  27.     Example:
  28.         get_example = _gen_getter("x.y")
  29.     is like:
  30.         def get_example(self):
  31.             if not x.parsed:
  32.                 x.parse()
  33.             return x.y
  34.     
  35.     """
  36.     def func(s):
  37.         attributes = attr.split(".")
  38.         attributes = map(lambda a: _attr_ext(a, s), attributes)
  39.         x = getattr(s, attributes[0])
  40.         attributes.insert(0, s)
  41.         if not x.parsed:
  42.             x.parse()
  43.         return reduce(getattr, attributes)
  44.     return func
  45.  
  46.         
  47. def _gen_setter(attr):
  48.     """ Returns a function to set the value of an attribute
  49.     
  50.     Example:
  51.         set_example = _gen_setter("x.y")
  52.     is like:
  53.         def set_example(self, value):
  54.             if not x.parsed:
  55.                 x.parse()
  56.             x.y = value
  57.     
  58.     """
  59.     def func(s, value):
  60.         attributes = attr.split(".")
  61.         attributes = map(lambda a: _attr_ext(a, s), attributes)
  62.         x = getattr(s, attributes[0])
  63.         attributes.insert(0, s)
  64.         if not x.parsed:
  65.             x.parse()
  66.         setattr(reduce(getattr, attributes[:-1]), attributes[-1], value)
  67.     return func
  68.  
  69.  
  70. def sort(x,y,sort):
  71.     if sort == "nr":
  72.         return cmp(int(x.bugnumber), int(y.bugnumber))
  73.     elif sort == "importance":
  74.         return cmp(BUG.SORT_IMPORTANCE.index(x.importance),
  75.                         BUG.SORT_IMPORTANCE.index(y.importance))
  76.     elif sort == "status":
  77.         return cmp(BUG.SORT_STATUS.index(x.status),
  78.                         BUG.SORT_STATUS.index(y.status))
  79.  
  80.  
  81. def blueprint_sort(x,y,sort):
  82.     if sort == "priority":
  83.         return cmp(BLUEPRINT.SORT_PRIORITY.index(getattr(x,sort)),
  84.                                 BLUEPRINT.SORT_PRIORITY.index(getattr(y,sort)))
  85.     elif sort == "status":
  86.         return cmp(BLUEPRINT.SORT_STATUS.index(getattr(x,sort)),
  87.                                 BLUEPRINT.SORT_STATUS.index(getattr(y,sort)))
  88.     elif sort == "delivery":
  89.         return cmp(BLUEPRINT.SORT_DELIVERY.index(getattr(x,sort)),
  90.                                 BLUEPRINT.SORT_DELIVERY.index(getattr(y,sort)))
  91.     else:
  92.         return cmp(getattr(x,sort), getattr(y,sort))
  93.  
  94.  
  95.  
  96. class user(str):
  97.     
  98.     user_regex = re.compile(r"^(.+)\s\((\S+)\)$", re.UNICODE)
  99.     
  100.     @staticmethod
  101.     def parse_text_user(usr):
  102.         x = user.user_regex.search(unicode(usr, "UTF-8"))
  103.         if x:
  104.             return user(x.group(2), x.group(1))
  105.         return usr
  106.         
  107.     @staticmethod
  108.     def parse_html_user(node):
  109.         """ takes a lp standard user node and returns a user object.
  110.         
  111.         Example for such a node:
  112.         * <a href="/~ogra">Oliver Grawert</a>
  113.         * <a href="https://blueprints.edge.launchpad.net/~ogra">
  114.                 <img alt="" width="14" height="14" src="/@@/person" /> Oliver Grawert
  115.           </a>
  116.         """
  117.         realname = unicode(node.content.strip("\n "), "UTF-8")
  118.         realname = realname.lstrip(u"\xa0")
  119.         return user(unicode(node.prop('href').split('~').pop().split("/")[0], "UTF-8"), realname)
  120.     
  121.     def __new__(cls, lplogin, realname=None, attributes=None):
  122.         obj = super(user, cls).__new__(user, lplogin)
  123.         obj.__lplogin = lplogin
  124.         obj.__realname = realname
  125.         if attributes is None:
  126.             attributes = set()
  127.         obj.__attributes = attributes
  128.         return obj
  129.         
  130.     @property
  131.     def realname(self):
  132.         return self.__realname or "unknown"
  133.         
  134.     @property
  135.     def lplogin(self):
  136.         return self.__lplogin
  137.  
  138.     @property
  139.     def _attributes(self):
  140.         return self.__attributes
  141.  
  142.     def __repr__(self):
  143.         # Does __repr__ really have to return an "ascii"-encoded string? how can we use an unicode one?
  144.         f =  "<user %s (%s)>" %(self.__lplogin, self.realname)
  145.         return f.encode("ascii", "replace")
  146.         
  147.     def __str__(self):
  148.         return self.__lplogin or ""
  149.         
  150.     def __nonzero__(self):
  151.         if self.__lplogin:
  152.             return True
  153.         else:
  154.             return False
  155.  
  156.  
  157.  
  158. class product(str):
  159.     
  160.     product_regex = re.compile(r"^(\S+)(\s\(([\w ]+)\))?$", re.UNICODE)
  161.     
  162.     @staticmethod
  163.     def parse_text_product(prod_str):
  164.         x = product.product_regex.search(prod_str)
  165.         if x:
  166.             #print x.groups()
  167.             target = None
  168.             a = x.group(3)
  169.             if a:
  170.                 a = a.split()
  171.                 if len(a) > 1:
  172.                     target = a[-1]
  173.                 longname = "%s (%s)" %(x.group(1), a[0])
  174.             else:
  175.                 longname = x.group(1)
  176.             return product(x.group(1), longname), target
  177.         # prod_str like 'Ubuntu Breezy' is also possible
  178.         x = prod_str.split()
  179.         if len(x) == 2:
  180.             if x[0].istitle():
  181.                 return product(x[0].lower(), x[0]), x[1]
  182.         return prod_str, None
  183.     
  184.     def __new__(cls, lpname, longname=None, type=None, tracked_in=None):
  185.         obj = super(product, cls).__new__(product, lpname)
  186.         obj.__lpname = lpname
  187.         obj.__longname = longname
  188.         obj.__type = type
  189.         obj.__tracked_in = tracked_in
  190.         return obj
  191.         
  192.     @property
  193.     def longname(self):
  194.         return self.__longname or self.__lpname or "unknown"
  195.         
  196.     @property
  197.     def type(self):
  198.         return self.__type
  199.         
  200.     @property
  201.     def tracked_in(self):
  202.         return self.__tracked_in
  203.         
  204.     def __str__(self):
  205.         return self.__lpname or ""
  206.         
  207.     def __repr__(self):
  208.         return "<product %s (%s, type=%s, tracked in=%s)>" %(self.__lpname,
  209.                     self.longname, self.__type, self.__tracked_in)
  210.         
  211.     def __nonzero__(self):
  212.         if self.__lpname:
  213.             return True
  214.         else:
  215.             return False
  216.  
  217.  
  218. class change_obj(object):
  219.     """ shows the status of a changed object  """
  220.     def __init__(self, attr, action="changed"):
  221.         """
  222.         * attr: edited attribute
  223.         * action: describes the way the attribute was edited
  224.         """
  225.         self.__attr = attr
  226.         self.__action = action
  227.         
  228.     @property
  229.     def component(self):
  230.         return self.__attr
  231.         
  232.     @property
  233.     def action(self):
  234.         return self.__action
  235.         
  236.     def __str__(self):
  237.         if self.action == "changed":
  238.             s = "(%s changed: %s)" %(repr(self.__attr), ", ".join([str(x) for x in getattr(self.__attr,"changed", [])]))
  239.         else:
  240.             s = "(%s %s)" %(repr(self.__attr), self.action)
  241.         return s
  242.         
  243.     def __repr__(self):
  244.         return "<Changes to %s>" %self.__attr
  245.         
  246.  
  247. class LateBindingProperty(property) :
  248.     ''' Allow late bindig properties.
  249.     
  250.     Thanks to Maric Michaud,
  251.     http://mail.python.org/pipermail/python-list/2006-September/401908.html'''
  252.     
  253.     __doc__ = property.__dict__['__doc__'] # see bug #576990
  254.  
  255.     def __init__(self, fget=None, fset=None, fdel=None, doc=None) :
  256.         if fget : fget = lambda s, n=fget.__name__ : getattr(s, n)()
  257.         if fset : fset = lambda s, v, n=fset.__name__ : getattr(s, n)(v)
  258.         if fdel : fdel = lambda s, n=fdel.__name__ : getattr(s, n)()
  259.         property.__init__(self, fget, fset, fdel, doc)
  260.